Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

79장. IAM Role 활용 — EC2 · ECS Task Role · Execution Role

이 장에서 말하고자 하는 것

앞 장에서 IAM의 4축을 봤다.

이 장은 실전에서 가장 자주 다루는

Role의 활용 패턴

을 정리한다.

특히 ECS 환경에서 헷갈리는 두 Role을 명확히 한다.

  • Execution Role
  • Task Role

1. Trust Policy vs Permission Policy

Role은 두 종류의 정책을 가진다.

Trust Policy    : 누가 이 Role을 받을 수 있나
Permission Policy: 받은 사람이 무엇을 할 수 있나

EC2 인스턴스에 붙이는 Role의 Trust Policy:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "ec2.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}

이러면 “EC2 서비스가 이 Role을 받을 수 있다” 가 된다.


2. EC2 Instance Profile

EC2가 Role을 직접 받을 수는 없다.
중간에 Instance Profile 을 거친다.

[Role]
  ↓ 담는다
[Instance Profile]
  ↓ EC2에 붙는다
[EC2 instance]
  ↓ 임시 자격증명 자동 발급
[Application]
  ↓ AWS SDK 호출 → S3 / DynamoDB / …

콘솔에서 Role을 만들면 Instance Profile이 자동으로 만들어진다.
Terraform에서는 명시적으로 만들어야 한다.


3. ECS의 두 Role — Execution vs Task

ECS에서는 두 종류의 Role 이 있다.

[ECS Task Definition]
  ├─ executionRoleArn   ← Execution Role
  └─ taskRoleArn        ← Task Role

Execution Role

Task를 띄우기 위해 ECS 에이전트가 쓰는 권한

  • ECR 이미지 pull
  • CloudWatch Logs에 로그 쓰기
  • Secrets Manager에서 비밀 가져오기 (secrets 필드)

Task Role

Task 안의 컨테이너가 AWS API를 호출할 때 쓰는 권한

  • S3 GetObject
  • DynamoDB Query
  • SQS SendMessage

4. 두 Role을 헷갈리면 일어나는 증상

Task가 시작 안 됨        → Execution Role 문제
  - "이미지 못 가져와요"
  - "로그 그룹에 못 써요"
  - "Secret 못 읽어요"

Task는 떴는데 API 거부됨  → Task Role 문제
  - "S3 GetObject denied"
  - "DynamoDB Query unauthorized"

이 두 증상이 운영에서 가장 자주 마주친다.


5. Lambda Role

Lambda 함수도 자기 Role을 가진다.

[Lambda]
  ├─ Execution Role (Lambda가 받음)
  │   ├─ CloudWatch Logs 쓰기
  │   └─ 함수가 호출할 AWS API 권한
  └─ 자동 발급되는 임시 자격증명

ECS와 달리 Execution Role / Task Role 구분이 없다 — Lambda는 한 Role.


6. Cross-Account Role — 다른 계정에 권한 빌려주기

[A 계정의 Role: ReadOnlyRoleForB]
  Trust Policy: B 계정만 받을 수 있음

[B 계정 사용자] → AssumeRole → 임시 자격증명 → A 계정 자원 접근
  • 멀티 계정 환경에서 표준
  • AWS Organizations 환경에 자주 등장
  • 외부 서드파티(DataDog · 빌링 도구 등) 에 권한 줄 때도 사용

7. OIDC Federation — 외부 신원으로 Role 받기

GitHub Actions · GitLab · Kubernetes ServiceAccount 같은 외부 신원이
Role을 받을 수 있다.

[GitHub Actions Workflow]
  ↓ OIDC 토큰 발급
[AWS IAM OIDC Provider]
  ↓ AssumeRoleWithWebIdentity
[Role: GitHubDeployRole]
  ↓ 임시 자격증명
[배포 작업]
  • CI에 액세스 키를 박지 않는다
  • 짧은 임시 자격증명만 사용
  • 어느 워크플로우인지 추적 가능

새 CI/CD는 거의 항상 OIDC로 풀어야 한다


8. 우리 서비스에서

Execution Role (공용)
  ├─ ecr:GetAuthorizationToken
  ├─ ecr:BatchGetImage
  ├─ logs:CreateLogStream / PutLogEvents
  └─ secretsmanager:GetSecretValue (특정 시크릿만)

Task Role (서비스마다 별도)
  orders-task:
    ├─ rds-db:connect (orders-db 만)
    └─ sns:Publish (order-events 토픽만)
  users-task:
    └─ rds-db:connect (users-db 만)
  catalog-task:
    └─ dynamodb:Query / GetItem (products 테이블만)

GitHub Actions Role (OIDC)
  ├─ ecr push
  ├─ ecs update-service
  └─ cloudfront create-invalidation

각 Role은 자기 일에 필요한 권한만 가진다.


9. 직접 확인해보기 — CLI

Role 만들기 (Trust Policy)

aws iam create-role \
  --role-name orders-task \
  --assume-role-policy-document '{
    "Version":"2012-10-17",
    "Statement":[{
      "Effect":"Allow",
      "Principal":{"Service":"ecs-tasks.amazonaws.com"},
      "Action":"sts:AssumeRole"
    }]
  }'

EC2 Instance Profile

aws iam create-instance-profile --instance-profile-name web
aws iam add-role-to-instance-profile \
  --instance-profile-name web \
  --role-name web-role

AssumeRole로 임시 자격증명 받기 (Cross-Account)

aws sts assume-role \
  --role-arn arn:aws:iam::123456789:role/ReadOnly \
  --role-session-name my-session

10. 코드로는 이렇게 생겼다 — Terraform (ECS Task Roles)

# Execution Role (모든 ECS Task가 공용으로 받음)
resource "aws_iam_role" "task_execution" {
  name = "ecs-task-execution"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ecs-tasks.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_role_policy_attachment" "task_execution_basic" {
  role       = aws_iam_role.task_execution.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

# orders 서비스 Task Role
resource "aws_iam_role" "orders_task" {
  name = "orders-task"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ecs-tasks.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_role_policy" "orders_task_perms" {
  role = aws_iam_role.orders_task.name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = "sns:Publish"
        Resource = aws_sns_topic.order_events.arn
      }
    ]
  })
}

task_role_arnexecution_role_arn 을 명확히 분리한다.


11. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. Execution Role과 Task Role을 합친다

보안이 약해진다 (불필요한 권한이 컨테이너 안에 그대로 보임).

안티패턴 2. 한 Task Role을 모든 서비스에 공용으로 쓴다

한 서비스의 권한이 모든 서비스에 흘러간다.

서비스마다 별도 Task Role, 각자 최소 권한

안티패턴 3. CI에 IAM User 키를 박는다

키 유출이 곧 운영 사고로 이어진다.

OIDC + AssumeRole로 키 없이 풀어낸다

안티패턴 4. AssumeRole 권한을 너무 넓게 준다

“누구나 어떤 Role이든 받아갈 수 있다” 같은 Trust Policy는 사고난다.

Trust Policy도 최소 범위로


12. 한 줄로 정리

Role은 머신/외부 신원에 임시 자격증명을 발급하는 도구이며,
ECS의 Execution / Task Role 분리와 CI의 OIDC 활용이 운영의 토대다


13. 이 장의 핵심 정리

  1. Role은 Trust Policy(누가 받을 수 있나) + Permission Policy(무엇을 할 수 있나) 다.
  2. EC2는 Instance Profile을 거쳐 Role을 받는다.
  3. ECS는 Execution Role(Task 띄움용) + Task Role(컨테이너 코드용) 두 가지가 있다.
  4. Lambda는 Execution Role 하나만 가진다.
  5. Cross-Account · OIDC Federation으로 외부 신원에도 Role을 줄 수 있다.
  6. CI/CD는 OIDC로 키 없이 운영하는 게 표준이다.